home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / MATH / PASCMP / PASFFT.PAS < prev    next >
Pascal/Delphi Source File  |  1994-06-29  |  5KB  |  211 lines

  1. { Complex Fast Fourier Transform Unit for Borland Pascal      }
  2. { (as an example for using complex mathematics unit PasCmplx) }
  3. { (c)1994 by Alex Klimovitski                                 }
  4.  
  5. { Based on algorithm from:                                    }
  6. { Marple, S.L. Digital Spectral Analysis. Prentice-Hall, Inc.,}
  7. {   Englewood Cliffs, N.J., 1988.                             }
  8.  
  9. { See FFTTEST.PAS for examples of using.                      }
  10.  
  11. unit PasFFT;
  12.  
  13. {$N+}
  14. {$G+}
  15.  
  16. interface
  17.  
  18. uses PasCmplx;
  19.  
  20. type
  21.   PCmplxArr = ^TCmplxArr;
  22.   TCmplxArr = array[1..4096] of Complex;
  23.  
  24. function CFFTInit(N: Integer; IsInverse: Boolean): Boolean;
  25. {initializes the unit for the transform of N points.
  26.  N -- number of points. N MUST be an integer power of 2,
  27.    for ex.: 64, 1024, 4096.
  28.  IsInverse -- false for direct Fourier tramsform,
  29.    true for inversed Fourier transform.
  30.  The function returns true if initialization was successful.
  31.  NOTE: You don't need to call this function explicitly.
  32. }
  33.  
  34. procedure CFFTClear;
  35. {returns the memory occupied by internal tables to the heap.
  36.  NOTE: You can call this function to free memory if you don't
  37.    need to perform more transforms. This function is called
  38.    automatically when the program ends.
  39. }
  40.  
  41. function CFFT(N: Integer; IsInverse: Boolean; X: PCmplxArr; T: Double): Boolean;
  42. {performs Fast Fourier Transform.
  43.  N -- number of points. N MUST be an integer power of 2.
  44.  IsInverse -- false for direct Fourier tramsform,
  45.    true for inversed Fourier transform.
  46.  X -- Pointer on an array of N complex numbers to be transformed.
  47.  T -- time step
  48.  The result is placed in array pointed by X.
  49.  The function returns true if transform was successful and false
  50.    if it failed.
  51.  NOTE: Subsequent transforms with the same number of points N and
  52.    in the same direction IsInverse are performed quicker because
  53.    of using of the same internal table.
  54. }
  55.  
  56. implementation
  57.  
  58. const
  59.   GW: PCmplxArr = nil;
  60.  
  61. var
  62.   GN: Integer;
  63.   GNExp: Integer;
  64.   GIsInverse: Boolean;
  65.  
  66. function CFFTInit(N: Integer; IsInverse: Boolean): Boolean;
  67. var
  68.   P, Q: Complex;
  69.   S, C: Double;
  70.   I: Integer;
  71. begin
  72.   CFFTInit := false;
  73.  
  74.   GNExp := 0;
  75.   I := 1;
  76.   while I < N do
  77.   begin
  78.     I := I * 2;
  79.     Inc(GNExp);
  80.   end;
  81.   if I <> N then Exit;
  82.  
  83.   GN := N;
  84.   GIsInverse := IsInverse;
  85.  
  86.   S := 8.0 * ArcTan(1.0) / GN;
  87.   CSinCosR(S, S, C);
  88.   P := Cmplx(C, S);
  89.  
  90.   if IsInverse then P := Conjug(P);
  91.  
  92.   GetMem(GW, GN * SizeOf(Complex));
  93.   if GW = nil then Exit;
  94.   Q := C1;
  95.  
  96.   for I := 1 to GN do
  97.   begin
  98.     GW^[I] := Q;
  99.     Q := CMul(Q, P);
  100.   end;
  101.  
  102.   CFFTInit := true;
  103. end;
  104.  
  105. procedure CFFTClear;
  106. begin
  107.   if GW <> nil then
  108.     FreeMem(GW, GN * SizeOf(Complex));
  109.   GN := 0;
  110. end;
  111.  
  112. function CFFT(N: Integer; IsInverse: Boolean; X: PCmplxArr; T: Double): Boolean;
  113. var
  114.   P, Q: Complex;
  115.   I, J, K, JJ, KK, LL, MM, NN: Integer;
  116. begin
  117.   CFFT := false;
  118.  
  119.   if X = nil then Exit;
  120.  
  121.   if (GW = nil) or (GN <> N) or (GIsInverse <> IsInverse) then
  122.   begin
  123.     CFFTClear;
  124.     if not CFFTInit(N, IsInverse) then Exit;
  125.   end;
  126.  
  127.   MM := 1;
  128.   LL := GN;
  129.  
  130.   for K := 1 to GNExp do
  131.   begin
  132.     NN := LL div 2;
  133.     JJ := MM + 1;
  134.  
  135.     I := 1;
  136.     while I <= GN do
  137.     begin
  138.       KK := I + NN;
  139.       P := CAdd(X^[I], X^[KK]);
  140.       X^[KK] := CSub(X^[I], X^[KK]);
  141.       X^[I] := P;
  142.       Inc(I, LL);
  143.     end; {while I}
  144.  
  145.     {if NN = 1 then Continue;}
  146.  
  147.     for J := 2 to NN do
  148.     begin
  149.       Q := GW^[JJ];
  150.  
  151.       I := J;
  152.       while I <= GN do
  153.       begin
  154.         KK := I + NN;
  155.         P := CAdd(X^[I], X^[KK]);
  156.         X^[KK] := CMul(CSub(X^[I], X^[KK]), Q);
  157.         X^[I] := P;
  158.         Inc(I, LL);
  159.       end; {while I}
  160.       JJ := JJ + MM;
  161.     end; {for J}
  162.  
  163.     LL := NN;
  164.     MM := MM * 2;
  165.   end; {for K}
  166.  
  167.   NN := GN div 2;
  168.   MM := N - 1;
  169.   J := 1;
  170.  
  171.   for I := 1 to MM do
  172.   begin
  173.     if I < J then
  174.     begin
  175.       P := X^[J];
  176.       X^[J] := X^[I];
  177.       X^[I] := P;
  178.     end; {if I < J}
  179.  
  180.     K := NN;
  181.     while K < J do
  182.     begin
  183.       Dec(J, K);
  184.       K := K div 2;
  185.     end; {while K < J}
  186.  
  187.     Inc(J, K);
  188.   end; {for I}
  189.  
  190.   if IsInverse then P := Cmplx(1.0 / (T * GN), 0.0)
  191.   else P := Cmplx(T, 0.0);
  192.  
  193.   for I := 1 to GN do
  194.     X^[I] := CMul(X^[I], P);
  195.  
  196.   CFFT := true;
  197. end;
  198.  
  199. var
  200.   ExitSave: Pointer;
  201.  
  202. procedure CFFTExit; far;
  203. begin
  204.   ExitProc := ExitSave;
  205.   CFFTClear;
  206. end;
  207.  
  208. begin
  209.   ExitSave := ExitProc;
  210.   ExitProc := @CFFTExit;
  211. end.